#include "CharacterController.h"
#include "Transformation.h"
#include "Point.h"
#include "Logger.h"
#include "Exception.h"
#include "Helpers.hpp"

using namespace game_engine;
using namespace game_engine::components;
using namespace game_engine::utils;

///////////////////////////////////////////////////////////////////////////////
// Constructors and Destructors
///////////////////////////////////////////////////////////////////////////////

CharacterController::CharacterController(void)
    : Component(), speed(1.0)
{
    type = "CharacterController";
}

CharacterController::CharacterController(GameObject *obj, const FLOAT32 spd)
    : Component(obj), speed(spd)
{
    type = "CharacterController";
}

CharacterController::~CharacterController(void)
{
}

///////////////////////////////////////////////////////////////////////////////
// Other public methods
///////////////////////////////////////////////////////////////////////////////

void CharacterController::update(const FLOAT32 time)
{
    // Check keyboard
    Point offset(0.0, 0.0);
    if (keyPressed(GLUT_KEY_UP))
    {
        Logger::INFO(GAMEENGINE_LOG, "GLUT_KEY_UP pressed");
        offset.setY(5.0);
    }
    else if (keyPressed(GLUT_KEY_DOWN))
    {
        Logger::INFO(GAMEENGINE_LOG, "GLUT_KEY_DOWN pressed");
        offset.setY(-5.0);
    }
    else if (keyPressed(GLUT_KEY_LEFT))
    {
        Logger::INFO(GAMEENGINE_LOG, "GLUT_KEY_LEFT pressed");
        offset.setX(-5.0);
    }
    else if (keyPressed(GLUT_KEY_RIGHT))
    {
        Logger::INFO(GAMEENGINE_LOG, "GLUT_KEY_RIGHT pressed");
        offset.setX(5.0);
    }

    // Get Transformation component and update its position
    if (offset != Point())
    {
        try
        {
            Transformation *t = 
                dynamic_cast<Transformation*> (getComponent(object, "Transformation"));

            // TODO : define operator+ for Point class
            //t->setPosition(t->getPosition() + offset);
            t->setPosition(Point(t->getXPosition() + offset.getX(), 
                t->getYPosition() + offset.getY()));

            Logger::DEBUG(GAMEENGINE_LOG, "CharacterController::update");
            Logger::DEBUG(GAMEENGINE_LOG, string("\tPosition X = ") + 
                to_string<FLOAT32>(t->getXPosition(), dec));
            Logger::DEBUG(GAMEENGINE_LOG, string("\tPosition Y = ") +
                to_string<FLOAT32>(t->getYPosition(), dec));

        } catch (exception &e)
        {
            Logger::ERR(GAMEENGINE_LOG, e.what());
            return;
        }
    }  // if (offset != Point())
}

///////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////

const FLOAT32 CharacterController::getSpeed(void) const
{
    return speed;
}

///////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////

void CharacterController::setSpeed(const FLOAT32 spd)
{
    speed = spd;
}
